﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Microsoft.BizTalk.Streaming;
using Microsoft.BizTalk.Message.Interop;
using Microsoft.BizTalk.Operations;
using Microsoft.BizTalk.Edi.Shared;
using Microsoft.XLANGs.BaseTypes;

namespace Locallab.Ack999Helper.BusinessContextReader
{
    internal abstract class X12Reader
    {        
        private int nTransactionSetOrdinal = 1;
        private int nFileLineNumber = 1;
        private int nInterChangeControlNumber;
        private int nFunctionGroupNumber;
        private int nTransactionSetID;
        private InterChangeInformation interchange;
        protected FileHeaderData delimiter { get; set; }

        protected virtual void ProcessX12Stream(ReadOnlySeekableStream x12MessageStream,StreamReader x12Reader)
        {
            var strData = string.Empty;
            var strReadData = string.Empty;
            var strTempData = string.Empty;
            var nCount = 0;
            var bufferSize = 4096;            
            var buffer = new char[bufferSize];
                       
            nCount = x12Reader.Read(buffer, 0, bufferSize);
            while (nCount != 0)
            {
                strData = GetString(buffer);
                strData = strTempData + strData;
                //strData = strData.Trim();

                if (strData.IndexOf(delimiter.SegmentDelimiter) > 0)
                {
                    while (true)
                    {
                        strReadData = strData.Substring(0, strData.IndexOf(delimiter.SegmentDelimiter)).Trim();
                        strData = strData.Substring(strData.IndexOf(delimiter.SegmentDelimiter) + 1);
                        ProcessSegment(strReadData);

                        if (!strData.Contains(delimiter.SegmentDelimiter))
                        {
                            strTempData = strData;
                            break;
                        }
                    }
                }

                Array.Clear(buffer, 0, bufferSize);
                nCount = x12Reader.Read(buffer, 0, bufferSize);
            }            
        }       

        private string GetString(char[] buffer)
        {
            return new string(buffer);
        }

        private void ProcessSegment(string strX12Segement)
        {
            var ediSegment = new EdiSegment(strX12Segement, this.delimiter.ElementDelimiter, this.delimiter.Version, nTransactionSetOrdinal);
            ediSegment.FileLineNumber = nFileLineNumber;
            nFileLineNumber++;

            //Console.WriteLine(nTransactionSetOrdinal + " " + strX12Segement + " " + ediSegment.Name + " " + ediSegment.IsBusinessID);

            if (ediSegment.Name == "ISA" || ediSegment.Name == "GS" || ediSegment.Name == "ST")
            {
                var strArrayElements = Utility.SplitSegment(ediSegment.Data, this.delimiter.ElementDelimiter);

                switch (ediSegment.Name)
                {
                    case "ISA":
                        {
                            interchange = new InterChangeInformation();
                            this.nInterChangeControlNumber = !strArrayElements[13].Equals(null) ? Convert.ToInt32(strArrayElements[13].Trim()) : 0;

                            interchange.AuthorizationInformationQualifier = !strArrayElements[1].Equals(null) ? strArrayElements[1].Trim() : string.Empty;
                            interchange.AuthorizationInformation = !strArrayElements[2].Equals(null) ? strArrayElements[2].Trim() : string.Empty;
                            interchange.SecurityInformationQualifier = !strArrayElements[3].Equals(null) ? strArrayElements[3].Trim() : string.Empty;
                            interchange.SecurityInformation = !strArrayElements[4].Equals(null) ? strArrayElements[4].Trim() : string.Empty;
                            interchange.InterchangeSenderIDQualifier = !strArrayElements[5].Equals(null) ? strArrayElements[5].Trim() : string.Empty;
                            interchange.InterchangeSenderID = !strArrayElements[6].Equals(null) ? strArrayElements[6].Trim() : string.Empty;
                            interchange.InterchangeReceiverIDQualifier = !strArrayElements[7].Equals(null) ? strArrayElements[7].Trim() : string.Empty;
                            interchange.InterchangeReceiverID = !strArrayElements[8].Equals(null) ? strArrayElements[8].Trim() : string.Empty;
                            interchange.InterchangeDate = !strArrayElements[9].Equals(null) ? strArrayElements[9].Trim() : string.Empty;
                            interchange.InterchangeTime = !strArrayElements[10].Equals(null) ? strArrayElements[10].Trim() : string.Empty;
                            interchange.InterchangeControlStandardsIdentifier = !strArrayElements[11].Equals(null) ? strArrayElements[11].Trim() : string.Empty;
                            interchange.InterchangeControlVersionNumber = !strArrayElements[12].Equals(null) ? strArrayElements[12].Trim() : string.Empty;
                            interchange.InterchangeControlNumber = this.nInterChangeControlNumber;
                            interchange.AcknowledgmentRequested = !strArrayElements[14].Equals(null) ? strArrayElements[14].Trim() : string.Empty;
                            interchange.UsageIndicator = !strArrayElements[15].Equals(null) ? strArrayElements[15].Trim() : string.Empty;
                        }
                        break;

                    case "GS":
                        {
                            this.nFunctionGroupNumber = !strArrayElements[6].Equals(null) ? Convert.ToInt32(strArrayElements[6].Trim()) : 0;

                            interchange.FunctionalIdentifier = !strArrayElements[1].Equals(null) ? strArrayElements[1].Trim() : string.Empty;
                            interchange.FunctionalSenderCode = !strArrayElements[2].Equals(null) ? strArrayElements[2].Trim() : string.Empty;
                            interchange.FunctionalReceiverCode = !strArrayElements[3].Equals(null) ? strArrayElements[3].Trim() : string.Empty;
                            interchange.FunctionalReceivedDate = !strArrayElements[4].Equals(null) ? strArrayElements[4].Trim() : string.Empty;
                            interchange.FunctionalReceivedTime = !strArrayElements[5].Equals(null) ? strArrayElements[5].Trim() : string.Empty;
                            interchange.FunctionalControlNumber = this.nFunctionGroupNumber;
                            interchange.ResponsibleAgency = !strArrayElements[7].Equals(null) ? strArrayElements[7].Trim() : string.Empty;
                            interchange.Version = !strArrayElements[8].Equals(null) ? strArrayElements[8].Trim() : string.Empty;

                            SaveInterChange();
                        }
                        break;

                    case "ST":
                        {
                            this.nTransactionSetID = !strArrayElements[2].Equals(null) ? Convert.ToInt32(strArrayElements[2].Trim()) : 0;
                            nTransactionSetOrdinal = 1;

                            if (this.nTransactionSetID == 220)
                                Console.WriteLine("Break");
                            
                        }
                        break;

                    default:
                        break;
                }
            }

            ediSegment.LineNumber = nTransactionSetOrdinal;

            if(ediSegment.IsBusinessID)
                ProcessEdiSegment(ediSegment);            

            nTransactionSetOrdinal++;
        }

        public abstract void ProcessEdiSegment(EdiSegment segment);        

        private void SaveInterChange()
        {
            if (interchange != null)
            {
                InterChangeHeader header = new InterChangeHeader(Guid.NewGuid().ToString());
                header.BeginInterChangeHeaderActivity();

                header.FileID = this.delimiter.FileID;
                header.AuthorizationInformationQualifier = interchange.AuthorizationInformationQualifier;
                header.AuthorizationInformation = interchange.AuthorizationInformation;
                header.SecurityInformationQualifier = interchange.SecurityInformationQualifier;
                header.SecurityInformation = interchange.SecurityInformation;
                header.InterchangeSenderIDQualifier = interchange.InterchangeSenderIDQualifier;
                header.InterchangeSenderID = interchange.InterchangeSenderID;
                header.InterchangeReceiverIDQualifier = interchange.InterchangeReceiverIDQualifier;
                header.InterchangeReceiverID = interchange.InterchangeReceiverID;
                header.InterchangeDate = interchange.InterchangeDate;
                header.InterchangeTime = interchange.InterchangeTime;
                header.InterchangeControlStandardsIdentifier = interchange.InterchangeControlStandardsIdentifier;
                header.InterchangeControlVersionNumber = interchange.InterchangeControlVersionNumber;
                header.InterchangeControlNumber = interchange.InterchangeControlNumber;
                header.AcknowledgmentRequested = interchange.AcknowledgmentRequested;
                header.UsageIndicator = interchange.UsageIndicator;
                header.FunctionalIdentifier = interchange.FunctionalIdentifier;
                header.FunctionalSenderCode = interchange.FunctionalSenderCode;
                header.FunctionalReceiverCode = interchange.FunctionalReceiverCode;
                header.FunctionalReceivedDate = interchange.FunctionalReceivedDate;
                header.FunctionalReceivedTime = interchange.FunctionalReceivedTime;
                header.FunctionalControlNumber = interchange.FunctionalControlNumber;
                header.ResponsibleAgency = interchange.ResponsibleAgency;
                header.VersionCode = interchange.Version;

                header.CommitInterChangeHeaderActivity();
                header.EndInterChangeHeaderActivity();
            }
        }

        protected void SaveBusinessIdentifier(BusinessContext bCtext)
        {
            Console.WriteLine(this.nInterChangeControlNumber+" "+ this.nTransactionSetID+" "+bCtext.FileLineNumber+" "+  bCtext.StartIndex + " " + bCtext.EndIndex + " " + bCtext.BusinessIDQualifier + " " + bCtext.BusinessID);

            EdiBusinessContext bContext = new EdiBusinessContext(Guid.NewGuid().ToString());
            bContext.BeginEdiBusinessContextActivity();

            bContext.FileID = this.delimiter.FileID;
            bContext.InterChangeControlNumber = this.nInterChangeControlNumber;
            bContext.FunctionalControlNumber = this.nFunctionGroupNumber;
            bContext.TransactionSetNumber = this.nTransactionSetID;
            bContext.StartIndex = bCtext.StartIndex;
            bContext.EndIndex = bCtext.EndIndex;
            bContext.BusinessIDQualifier = bCtext.BusinessIDQualifier;
            bContext.BusinessID = bCtext.BusinessID;
            bContext.LineNumber = bCtext.FileLineNumber;

            bContext.CommitEdiBusinessContextActivity();
            bContext.EndEdiBusinessContextActivity();
        }
    }
}
